#include "lm_conf_video_wrapper.h"

namespace lm {
	void CALLBACK FuncVideoOnDisconnectVideoServerCB(int result, void* clientdata) {
		ConfVideoWrapper* wrapper = reinterpret_cast<ConfVideoWrapper*>(clientdata);
		wrapper->OnDisconnectVideoServerCB(result);
	}

	void CALLBACK FuncVideoOnAddLocalPreviewCB(
		int id_device, int id_preview, uint64_t context, int error, void* clientdata) {
		ConfVideoWrapper* wrapper = reinterpret_cast<ConfVideoWrapper*>(clientdata);
		wrapper->OnAddLocalPreviewCB(id_device, id_preview, context, error);
	}

	void CALLBACK FuncVideoOnVideoDeviceChangedCB(
		int change_device, int is_add, int devnums, int main_dev_id, void* clientdata) {
		ConfVideoWrapper* wrapper = reinterpret_cast<ConfVideoWrapper*>(clientdata);
		wrapper->OnVideoDeviceChangedCB(change_device, is_add, devnums, main_dev_id);
	}

	void CALLBACK FuncVideoOnLocalVideoResolutionChangedCB(
		int id_device, int id_preview, int width, int height, void* clientdata) {
		ConfVideoWrapper* wrapper = reinterpret_cast<ConfVideoWrapper*>(clientdata);
		wrapper->OnLocalVideoResolutionChangedCB(id_device, id_preview, width, height);
	}

	void CALLBACK FuncVideoOnRemoteVideoResolutionChangedCB(
		const char* account, int id_device, int id_preview, int width, int height, void* clientdata) {
		ConfVideoWrapper* wrapper = reinterpret_cast<ConfVideoWrapper*>(clientdata);
		wrapper->OnRemoteVideoResolutionChangedCB(account, id_device, id_preview, width, height);
	}

	void ConfVideoWrapper::OnDisconnectVideoServerCB(int result) {
		for (ObserverList::iterator it = observer_list_.begin(); it != observer_list_.end(); it++) {
			(*it)->OnDisconnectVideoServer(result);
		}
	}

	void ConfVideoWrapper::OnAddLocalPreviewCB(
		int id_device, int id_preview, uint64_t context, int error) {
		for (ObserverList::iterator it = observer_list_.begin(); it != observer_list_.end(); it++) {
			(*it)->OnAddLocalPreview(id_device, id_preview, context, error);
		}
	}

	void ConfVideoWrapper::OnVideoDeviceChangedCB(
		int change_device, int is_add, int devnums, int main_dev_id) {
		for (ObserverList::iterator it = observer_list_.begin(); it != observer_list_.end(); it++) {
			(*it)->OnVideoDeviceChanged(change_device, !!is_add, devnums, main_dev_id);
		}
	}

	void ConfVideoWrapper::OnLocalVideoResolutionChangedCB(
		int id_device, int id_preview, int width, int height) {
		for (ObserverList::iterator it = observer_list_.begin(); it != observer_list_.end(); it++) {
			(*it)->OnLocalVideoResolutionChanged(id_device, id_preview, width, height);
		}
	}

	void ConfVideoWrapper::OnRemoteVideoResolutionChangedCB(
		const char* account, int id_device, int id_preview, int width, int height) {
		for (ObserverList::iterator it = observer_list_.begin(); it != observer_list_.end(); it++) {
			(*it)->OnRemoteVideoResolutionChanged(account, id_device, id_preview, width, height);
		}
	}

	void ConfVideoWrapper::SetStartImage(const char* jpg_file) {
		lm_conf_video_SetStartImage(jpg_file);
	}

	void ConfVideoWrapper::SetTimeoutImage(const char* jpg_file) {
		lm_conf_video_SetTimeoutImage(jpg_file);
	}

	void ConfVideoWrapper::SetRemoteDisableRemoteVideoImage(const char* jpg_file) {
		lm_conf_video_SetRemoteDisableRemoteVideoImage(jpg_file);
	}

	void ConfVideoWrapper::SetLocalDisableRemoteVideoImage(const char* jpg_file) {
		lm_conf_video_SetLocalDisableRemoteVideoImage(jpg_file);
	}

	void ConfVideoWrapper::SetLocalDesktopCamearImage(const char* jpg_file) {
		lm_conf_video_SetLocalDesktopCamearImage(jpg_file);
	}


	ConfVideoWrapper::ConfVideoWrapper(native_object_t c_object)
		: c_object_(c_object) {
		ConfVideoCallback cb;
		memset(&cb, 0, sizeof(cb));
		cb.client_data_ = this;
		cb.OnAddLocalPreview_ = FuncVideoOnAddLocalPreviewCB;
		cb.OnDisconnectVideoServer_ = FuncVideoOnDisconnectVideoServerCB;
		cb.OnLocalVideoResolutionChanged_ = FuncVideoOnLocalVideoResolutionChangedCB;
		cb.OnRemoteVideoResolutionChanged_ = FuncVideoOnRemoteVideoResolutionChangedCB;
		cb.OnVideoDeviceChanged_ = FuncVideoOnVideoDeviceChangedCB;
		lm_conf_video_set_callback(c_object_, &cb);
	}

	ConfVideoWrapper::~ConfVideoWrapper() {
	}

	void ConfVideoWrapper::AddObserver(Observer* observer) {
		if (std::find(observer_list_.begin(), observer_list_.end(), observer) == observer_list_.end())
			observer_list_.push_back(observer);
	}

	void ConfVideoWrapper::RemoveObserver(Observer* observer) {
		ObserverList::iterator it = std::find(observer_list_.begin(), observer_list_.end(), observer);
		if (it != observer_list_.end())
			observer_list_.erase(it);
	}

	int ConfVideoWrapper::AddLocalPreview(
		DeviceIdentity id_device,
		void* windows,
		uint64_t context,
		const unsigned int z_order,
		const float left,
		const float top,
		const float right,
		const float bottom,
		int& id_preview) {
		return lm_conf_video_AddLocalPreview(c_object_,
			id_device, windows, context, z_order, left, top, right, bottom, &id_preview);
	}

	int ConfVideoWrapper::ConfigureLocalPreview(
		DeviceIdentity id_device,
		int id_preview,
		const unsigned int z_order,
		const float left,
		const float top,
		const float right,
		const float bottom) {
		return lm_conf_video_ConfigureLocalPreview(c_object_,
			id_device, id_preview, z_order, left, top, right, bottom);
	}

	int ConfVideoWrapper::ChangeLocalPreviewWindow(
		DeviceIdentity id_device,
		int id_preview, void* window,
		const unsigned int z_order,
		const float left,
		const float top,
		const float right,
		const float bottom) {
		return lm_conf_video_ChangeLocalPreviewWindow(c_object_,
			id_device, id_preview, window, z_order, left, top, right, bottom);
	}

	int ConfVideoWrapper::RemoveLocalPreview(DeviceIdentity id_device, int id_preview) {
		return lm_conf_video_RemoveLocalPreview(c_object_,
			id_device, id_preview);
	}

	int ConfVideoWrapper::EnableMirrorLocalPreview(DeviceIdentity id_device, int id_preview,
		bool enable, bool mirror_xaxis, bool mirror_yaxis) {
		return lm_conf_video_EnableMirrorLocalPreview(c_object_,
			id_device, id_preview, enable ? 1 : 0, mirror_xaxis ? 1 : 0, mirror_yaxis ? 1 : 0);
	}

	int ConfVideoWrapper::MirrorLocalPreviewState(DeviceIdentity id_device, int id_preview,
		bool& enable, bool& mirror_xaxis, bool& mirror_yaxis) {
		int v1 = 0; int v2 = 0; int v3 = 0;
		int ret = lm_conf_video_MirrorLocalPreviewState(c_object_,
			id_device, id_preview, &v1, &v2, &v3); 
		enable = !!v1;
		mirror_xaxis = !!v2;
		mirror_yaxis = !!v3;
		return ret;
	}

	int ConfVideoWrapper::RotateLocalPreview(DeviceIdentity id_device,
		int id_preview, int rotation) {
		return lm_conf_video_RotateLocalPreview(c_object_,
			id_device, id_preview, rotation);
	}

	int ConfVideoWrapper::RotateLocalPreviewState(DeviceIdentity id_device,
		int id_preview, int& rotation) {
		return lm_conf_video_RotateLocalPreviewState(c_object_,
			id_device, id_preview, &rotation);
	}

	int ConfVideoWrapper::GetLocalPreviewResolution(
		DeviceIdentity id_device, int& width, int& height) {
		return lm_conf_video_GetLocalPreviewResolution(c_object_,
			id_device, &width, &height);
	}

	int ConfVideoWrapper::AddRemotePreview(
		const char* account,
		DeviceIdentity id_device,
		void* windows,
		const unsigned int z_order,
		const float left,
		const float top,
		const float right,
		const float bottom,
		int& id_preview) {
		return lm_conf_video_AddRemotePreview(c_object_,
			account, id_device, windows, z_order, left, top, right, bottom, &id_preview);
	}

	int ConfVideoWrapper::ConfigureRemotePreview(
		const char* account,
		DeviceIdentity id_device,
		int id_preview,
		const unsigned int z_order,
		const float left,
		const float top,
		const float right,
		const float bottom) {
		return lm_conf_video_ConfigureRemotePreview(c_object_,
			account, id_device, id_preview, z_order, left, top, right, bottom);
	}

	int ConfVideoWrapper::ChangeRemotePreviewWindow(
		const char* account,
		DeviceIdentity id_device,
		int id_preview,
		void* window,
		const unsigned int z_order,
		const float left,
		const float top,
		const float right,
		const float bottom) {
		return lm_conf_video_ChangeRemotePreviewWindow(c_object_,
			account, id_device, id_preview, window, z_order, left, top, right, bottom);
	}

	int ConfVideoWrapper::RemoveRemotePreview(const char* account,
		DeviceIdentity id_device, int id_preview) {
		return lm_conf_video_RemoveRemotePreview(c_object_,
			account, id_device, id_preview);
	}

	int ConfVideoWrapper::EnableMirrorRemotePreview(const char* account,
		DeviceIdentity id_device, int id_preview,
		bool enable, bool mirror_xaxis, bool mirror_yaxis) {
		return lm_conf_video_EnableMirrorRemotePreview(c_object_, account,
			id_device, id_preview, enable ? 1 : 0, mirror_xaxis ? 1 : 0, mirror_yaxis ? 1 : 0);
	}

	int ConfVideoWrapper::MirrorRemotePreviewState(const char* account,
		DeviceIdentity id_device, int id_preview,
		bool& enable, bool& mirror_xaxis, bool& mirror_yaxis) {
		int v1 = 0; int v2 = 0; int v3 = 0;
		int ret = lm_conf_video_MirrorRemotePreviewState(c_object_,
			account, id_device, id_preview, &v1, &v2, &v3);
		enable = !!v1;
		mirror_xaxis = !!v2;
		mirror_yaxis = !!v3;
		return ret;
	}

	int ConfVideoWrapper::RotateRemotePreview(const char* account,
		DeviceIdentity id_device, int id_preview, int rotation) {
		return lm_conf_video_RotateRemotePreview(c_object_,
			account, id_device, id_preview, rotation);
	}

	int ConfVideoWrapper::RotateRemotePreviewState(const char* account,
		DeviceIdentity id_device, int id_preview, int& rotation) {
		return lm_conf_video_RotateRemotePreviewState(c_object_,
			account, id_device, id_preview, &rotation);
	}

	int ConfVideoWrapper::EnableRemotePreviewColorEnhancement(const char* account,
		DeviceIdentity id_device, bool enable) {
		return lm_conf_video_EnableRemotePreviewColorEnhancement(c_object_,
			account, id_device, enable ? 1 : 0);
	}

	int ConfVideoWrapper::RemotePreviewColorEnhancementState(const char* account,
		DeviceIdentity id_device, bool& enable) {
		int v = 0;
		int ret = lm_conf_video_RemotePreviewColorEnhancementState(c_object_,
			account, id_device, &v);
		enable = !!v;
		return ret;
	}

	int ConfVideoWrapper::EnableRemotePreview(const char* account,
		DeviceIdentity id_device, bool enable) {
		return lm_conf_video_EnableRemotePreview(c_object_,
			account, id_device, enable ? 1 : 0);
	}

	int ConfVideoWrapper::GetRemotePreviewState(const char* account,
		DeviceIdentity id_device, bool& enable) {
		int v = 0;
		int ret = lm_conf_video_GetRemotePreviewState(c_object_,
			account, id_device, &v);
		enable = !!v;
		return ret;
	}

	int ConfVideoWrapper::GetRemotePreviewResolution(const char* account,
		DeviceIdentity id_device, int& width, int& height) {
		return lm_conf_video_GetRemotePreviewResolution(c_object_,
			account, id_device, &width, &height);
	}

	int ConfVideoWrapper::NumOfDevice(int& nums) {
		return lm_conf_video_NumOfDevice(c_object_, &nums);
	}

	int ConfVideoWrapper::EnumDevices(DeviceIdentity* id_devices, int& nums) {
		return lm_conf_video_EnumDevices(c_object_, reinterpret_cast<int*>(id_devices), &nums);
	}

	int ConfVideoWrapper::GetDeviceName(DeviceIdentity id_device,
		char* name, int name_size, char* guid, int guid_size) {
		return lm_conf_video_GetDeviceName(c_object_, id_device, name, name_size, guid, guid_size);
	}

	int ConfVideoWrapper::GetDeviceIdWithGuid(const char* guid,
		DeviceIdentity& id_device) {
		return lm_conf_video_GetDeviceIdWithGuid(c_object_, guid, reinterpret_cast<int*>(&id_device));
	}

	int ConfVideoWrapper::GetDeviceFormat(DeviceIdentity id_device,
		unsigned int *pixels, int& count) {
		return lm_conf_video_GetDeviceFormat(c_object_, id_device, pixels, &count);
	}

	int ConfVideoWrapper::OpenPropertypage(DeviceIdentity id_device,
		void* window, const char* title) {
		return lm_conf_video_OpenPropertypage(c_object_, id_device, window, title);
	}

	int ConfVideoWrapper::SwitchMobiledevicesCamera() {
		return lm_conf_video_SwitchMobiledevicesCamera(c_object_);
	}

	int ConfVideoWrapper::GetMobiledevicesActiveCameraId(DeviceIdentity& id_device) {
		return lm_conf_video_GetMobiledevicesActiveCamera(c_object_, reinterpret_cast<int*>(&id_device));
	}

	int ConfVideoWrapper::IsCaptureing(DeviceIdentity id_device, bool& value) {
		int v = 0;
		int ret = lm_conf_video_IsCaptureing(c_object_, id_device, &v);
		value = !!v;
		return ret;
	}

	int ConfVideoWrapper::SetVideoConfig(DeviceIdentity id_device, const LMVideoConfig& config) {
		return lm_conf_video_SetVideoConfig(c_object_, id_device, &config);
	}

	int ConfVideoWrapper::GetVideoConfig(DeviceIdentity id_device, LMVideoConfig& config) {
		return lm_conf_video_GetVideoConfig(c_object_, id_device, &config);
	}

	int ConfVideoWrapper::EnableDeflickering(DeviceIdentity id_device, bool enable) {
		return lm_conf_video_EnableDeflickering(c_object_, id_device, enable ? 1 : 0);
	}

	int ConfVideoWrapper::DeflickeringState(DeviceIdentity id_device, bool& enable) {
		int v = 0;
		int ret = lm_conf_video_DeflickeringState(c_object_, id_device, &v);
		enable = !!v;
		return ret;
	}

	int ConfVideoWrapper::GetCaptureDeviceSnapshot(DeviceIdentity id_device,
		const char* file_name) {
		return lm_conf_video_GetCaptureDeviceSnapshot(c_object_, id_device, file_name);
	}

	int ConfVideoWrapper::GetRenderSnapshot(const char* account,
		DeviceIdentity id_device, int id_preview,
		const char* file_name) {
		return lm_conf_video_GetRenderSnapshot(c_object_, account, id_device, id_preview, file_name);
	}

	int ConfVideoWrapper::SetShowNameInVideo(bool enable) {
		return lm_conf_video_SetShowNameInVideo(c_object_, enable ? 1 : 0);
	}

	int ConfVideoWrapper::GetShowNameInVideoState(bool& enable) {
		int v = 0;
		int ret = lm_conf_video_GetShowNameInVideoState(c_object_, &v);
		enable = !!v;
		return ret;
	}

	int ConfVideoWrapper::EnableDebugVideo(bool enable) {
		return lm_conf_video_EnableDebugVideo(c_object_, enable ? 1 : 0);
	}

	int ConfVideoWrapper::GetDebugVideoState(bool& enable) {
		int v = 0;
		int ret = lm_conf_video_GetDebugVideoState(c_object_, &v);
		enable = !!v;
		return ret;
	}

	int ConfVideoWrapper::GetCameraType(DeviceIdentity id_device, LMCameraType& type) {
		return lm_conf_video_GetCameraType(c_object_, id_device, reinterpret_cast<int*>(&type));
	}

	int ConfVideoWrapper::AddIPCamera(const LMIPCameraInfo* info,
		int channel, bool is_main_stream, const char* name) {
		return lm_conf_video_AddIPCamera(c_object_, info, channel, is_main_stream ? 1 : 0, name);
	}

	int ConfVideoWrapper::RemoveIPCamera(int identity,
		int channel, bool is_main_stream) {
		return lm_conf_video_RemoveIPCamera(c_object_, identity, channel, is_main_stream ? 1 : 0);
	}

	int ConfVideoWrapper::AddRAWDataCamera(int identity, const char* name) {
		return lm_conf_video_AddRAWDataCamera(c_object_, identity, name);
	}

	int ConfVideoWrapper::RemoveRAWDataCamera(int identity) {
		return lm_conf_video_RemoveRAWDataCamera(c_object_, identity);
	}

	int ConfVideoWrapper::IncomingRAWData(
		int identity, const void* data, size_t data_len,
		int width, int height, LMRawVideoType type) {
		return lm_conf_video_IncomingRAWData(c_object_, identity, data, static_cast<int>(data_len), width, height, type);
	}

}